#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int isPrime(int n);
int eIsStandard(int e,int fai_n);
int gcd(int m,int n);
int countD(int e,int n);
int *inputString(int *m_len);//将输入的一串字符转换为一组数字，放在整型数组里面
int encodeString(int e,int n);  //加密函数 
int decodeString(int d,int n);   //解密函数 
int outputString(int * intStr,int d,int n,int len);

long long powMod(long long a,long long b,long long c);


int main() {
	while(1) {

		int p,q,e,d,n,fai_n;
		printf("请输入p,q的值\n");
		int flag1,flag2,flag3;
		scanf("%d%d",&p,&q);
		flag1 = isPrime(p);
		flag2 = isPrime(q);
		//printf("flag1 p :%d  flag2 q :%d\n",flag1,flag2);
		if(flag1==1&&flag2==1) {
			n = p*q;
			fai_n = (p-1)*(q-1);
			printf("p:%d  q:%d n:%d  fai_n:%d\n",p,q,n,fai_n);
            printf("请输入e的值!\n");
            scanf("%d",&e);
            //判断e是否满足 1<e< fai(n)，且gcd(fai(n),e)=1
            flag3=eIsStandard(e,fai_n);
            if(flag3==1){
            	printf("输入的e符合条件!\n");
            	//计算d，满足 d·e≡1 mod fai(n)
            	d = countD(e,fai_n);
            	printf("d: %d\n",d);
            	
            	//现在 以{e,n}为公开钥,{d,p,q}为秘密钥  齐全了
				
                /*inputString();
                encodeString();
                decodeString();*/
                
                int choice;
				printf("请选择: 1,加密  2,解密\n");
				scanf("%d",&choice);
				getchar();
				switch(choice){
				case 1:
					encodeString(e,n);
					break;
				case 2:
					decodeString(d,n);
					break;
				}
			}else{
				printf("输入的e不符合条件!\n");
				printf("\n");
			}  
		}else{
			printf("\n");
			continue;
		}
	}

}

int isPrime(int n) {
	int flag,i;
	if(n<2) {
		flag = 0;
	} else {
		for(i=2; i<n; i++) {
			if(n%i==0) {
				//	flag = 0;
				break;
			}
		}
		if(i<n) {
			printf("%d不是素数!\n",n);
			flag = 0;
		} else {
			printf("%d是素数!\n",n);
			flag = 1;
		}
	}
	return flag;
}

int eIsStandard(int e,int fai_n){
	int flag = 0;
	int flag2= 0;
	if(e>1&&e<fai_n){
		flag2 = gcd(e,fai_n);
		if(flag2==1){
			flag = 1;
		}else{
			printf("最大公因数不为1!\n");
		}
	}
	else {
		printf("不在范围内!\n");
		flag = 0;
	}
	return flag;
}

int gcd(int m,int n){
	int flag = 0;
	int t,r;
	if(m<n){  //确保是大数除小数 
		t = m;
		m = n;
		n = t;
	}
	while((m%n)!=0){   //辗转相除 
		r = m%n;
		m = n;
		n = r; 
	}
	if(n==1){
		flag = 1;   //最大公因数为1，故互素 
	}else{
		flag = 0;   //不互素 
	}
	return flag ;
}

int countD(int e,int n){
	int k=0,d;
	for (k = 0; (k*n + 1) % e != 0; k++);  
	if ((k*n + 1) % e == 0)  
		d = (k*n + 1) / e;  //d * e ≡ 1 (mod Φ(n))  
	
	return d;
}


int *inputString(int *m_len){
     printf("请输入您要加密的字符串!\n");
     char * s = (char *)malloc(sizeof(char)*1000);
     scanf("%[^\n]s",s);
     int len= strlen(s);
     *m_len = len;
     printf("strlen: %d\n",len);
     int * intStr = (int * )malloc(sizeof(int)*len);
     int i=0;
     for(i=0;i<len;i++){
     	if(s[i]==' '){
     		intStr[i]=0;
		 }else if(s[i]>='A'&&s[i]<='Z'){
		 	intStr[i]=s[i]-64;
		 }else if(s[i]>='a'&&s[i]<='z'){
		 	intStr[i]=s[i]-96;
		 }
	 }
	 printf("intStr的内容!\n");
	 for(i=0;i<len;i++){
	 	printf("%d,",intStr[i]);
	 }
	 printf("\n");
     //getchar();
    // int * p = NULL;
     return intStr;
} 

int encodeString(int e,int n){
	printf("e:%d   n:%d\n",e,n);
	int m_len =0;
	int *intStr = inputString(&m_len);
//	printf("m_len:%d  intstr[0]:%d\n",m_len,intStr[0]);
	int * encodeRes = (int *)malloc(sizeof(int)*m_len);
	int i=0;
	for(i=0;i<m_len;i++){
		//printf("intStr[i]^e:%d\n",intStr[i]^e);
		encodeRes[i]=(int)powMod((long long)intStr[i],(long long)e,(long long)n);
		
	}
	printf("encodeRes(%d):\n",m_len);
	for(i=0;i<m_len;i++){
		//printf("intStr:  %d\n",intStr[i]);
		if(i==m_len-1){
			printf("%d",encodeRes[i]);
		}else{
			printf("%d,",encodeRes[i]);
		}
		
	}
	printf("\n");
	return 0;
}

int decodeString(int d,int n){
    printf("d:%d  n:%d\n",d,n);
    printf("请输入需解密字母的个数:\n");
    int num;
    scanf("%d",&num);
    getchar();
    int *intStr = (int *)malloc(sizeof(int)*num);
    int i=0;
    printf("请逐个输入密文:\n");
    for(i=0;i<num;i++){
    	scanf("%d",&intStr[i]);
	}
    /*printf("输入的密文为：\n");
	for(i=0;i<num;i++){
		printf("%d,",intStr[i]);
	}*/
	printf("\n");
    outputString(intStr,d,n,num);
    return 0;

} 



int outputString(int * intStr,int d,int n,int len){
	
	//printf("d:%d  n:%d  len:%d",d,n,len);
	printf("\n"); 
	int i=0;
	/*printf("intStr:\n");
	for(i=0;i<len;i++){
		printf("%d,",intStr[i]);
	}*/
	int * decodeRes = (int*)malloc(sizeof(int)*len);
	for(i=0;i<len;i++){
		decodeRes[i]=(int)powMod((long long)intStr[i],(long long)d,(long long)n);
	}
	printf("\ndecodeRes!\n");
	/*for(i=0;i<len;i++){
		printf("%d,",decodeRes[i]);
	}*/
	char * outputString = (char *)malloc(sizeof(char)*len);
	for(i=0;i<len;i++){
		if(decodeRes[i]==0){
			outputString[i]=' ';
		}else if(decodeRes[i]>=1&&decodeRes[i]<=26){
			outputString[i]=decodeRes[i]+64;
		}
	} 
	for(i=0;i<len;i++){
		printf("%c",outputString[i]);
	}
	printf("\n");
	
	
}


long long powMod(long long a,long long b,long long c)
{
    long long result = 1;
    //a = a%c;
    while(b>0)
    {
        if(b % 2 == 1)
            result = (result * a )% c;
        b >>=1;   //b = b/2;
        a = (a * a )% c; 
    }
    return  result;
}
